/*********************************************************************************************************
 *  ------------------------------------------------------------------------------------------------------
 *  file description
 *  ------------------------------------------------------------------------------------------------------
 *         \file  vector.h
 *        \brief  This is a general C language vector container module, which can dynamically adjust the size and general data structure
 *       \author  Lamdonn
 *        \email  Lamdonn@163.com
 *      \version  1.1.0
 *      \license  GPL2
 *    \copyright  Copyright (C) 2023 Lamdonn.
 ********************************************************************************************************/
#ifndef __vector_H
#define __vector_H

#include "iterator.h"
#include <stdlib.h>

/* vector type define */
typedef struct 
{
    VOBJECT parent;                     /* parent object */
    int capacity;                       /* capacity of vector */
} VECTOR, *vector_t;

/** 
 *  \brief create vector
 *  \param[in] dsize: size of vector item
 *  \param[in] size: size of vector
 *  \return vector handler or NULL: fial
 */
vector_t vector_create(int dsize, int size);

/** 
 *  \brief delete vector
 *  \param[in] vector: vector handler
 *  \return none
 */
void vector_delete(vector_t vector);

/** 
 *  \brief assign vector
 *  \param[in] vector: vector handler
 *  \param[in] data: address of new data
 *  \param[in] num: number of assign
 *  \return 1: success or 0: fail
 */
int vector_assign(vector_t vector, void* data, int num);

/** 
 *  \brief swap all items of two vector
 *  \param[in] vector: vector handler
 *  \param[in] swap: vector of need to swap
 *  \return 1: success or 0: fail
 */
int vector_swap(vector_t vector, vector_t swap);

/** 
 *  \brief get the address of vector's data
 *  \param[in] vector: vector handler
 *  \param[in] index: vector index
 *  \return address of vector's data or error address
 */
void* vector_data(vector_t vector, int index);

/** 
 *  \brief get the address of error data
 *  \param[in] vector: vector handler
 *  \return address of error data
 */
void* vector_error(vector_t vector);

/** 
 *  \brief reassign the length of the vector container vector
 *  \param[in] vector: vector handler
 *  \param[in] size: new size of vector
 *  \return 1: success or 0: fail
 */
int vector_resize(vector_t vector, int size);

/** 
 *  \brief increase the length of vector from the tail
 *  \param[in] vector: vector handler
 *  \param[in] data: data of new item
 *  \return 1: success or 0: fail
 */
int vector_push_back(vector_t vector, void* data);

/** 
 *  \brief Descrease the length of vector from the tail
 *  \param[in] vector: vector handler
 *  \return 1: success or 0: fail
 */
int vector_pop_back(vector_t vector);

/** 
 *  \brief insert data into vector
 *  \param[in] vector: vector handler
 *  \param[in] index: vector index
 *  \param[in] data: address of new data
 *  \param[in] num: number of inserts 
 *  \return 1: success or 0: fail
 */
int vector_insert(vector_t vector, int index, void* data, int num);

/** 
 *  \brief Erase data from vector
 *  \param[in] vector: vector handler
 *  \param[in] begin: Vector begin index
 *  \param[in] end: Vector end index
 *  \return 1: success or 0: fail
 */
int vector_erase(vector_t vector, int begin, int end);

/** 
 *  \brief clear all item of vector
 *  \param[in] vector: vector handler
 *  \return 1: success or 0: fail
 */
int vector_clear(vector_t vector);

/** 
 *  \brief get the size of vector
 *  \param[in] vector: vector handler
 *  \return size of vector
 */
int vector_size(vector_t vector);

/** 
 *  \brief judge whether the vector is empty
 *  \param[in] vector: vector handler
 *  \return 1: empty or 0: not empty
 */
int vector_empty(vector_t vector);

/** 
 *  \brief get the capacity of vector
 *  \param[in] vector: vector handler
 *  \return capacity of vector
 */
int vector_capacity(vector_t vector);

/** 
 *  \brief macro definition method for creating vector
 *  \param[in] type: tpye of item(e.g int char)
 *  \param[in] size: size of vector
 *  \return vector handler
 */
#define vector(type, size)              (vector_create(sizeof(type),(size)))

/** 
 *  \brief define a const vector, end use does not need to be deleted
 *  \param[in] type: tpye of item(e.g int char)
 *  \param[in] size: size of vector
 *  \return const vector
 */
#define const_vector(type, size)        &(VECTOR){1,(type[size]){},sizeof(type),size,size}

/** 
 *  \brief macro definition method for delete vector
 *  \param[in] vector: vector handler
 *  \return none
 */
#define _vector(vector)                 do{vector_delete(vector);(vector)=NULL;}while(0)

/** 
 *  \brief macro definition method for get item of vector
 *  \param[in] vector: vector handler
 *  \param[in] type: tpye of item
 *  \param[in] i: index of vector
 *  \return reference to the specified item
 */
#define vector_at(vector, type, i)      (*(type *)vector_data((vector),(i)))

/** 
 *  \brief macro definition method for get front item of vector
 *  \param[in] vector: vector handler
 *  \param[in] type: tpye of item
 *  \return reference to the specified item
 */
#define vector_front(vector, type)      vector_at(vector, type, 0)

/** 
 *  \brief macro definition method for get back item of vector
 *  \param[in] vector: vector handler
 *  \param[in] type: tpye of item
 *  \return reference to the specified item
 */
#define vector_back(vector, type)       vector_at(vector, type, ((vobject_t)(vector))->size-1)

/** 
 *  \brief macro definition method for degenerate vector to normal array(e.g. v2a(vector, int)[0] = 0;)
 *  \param[in] vector: vector handler
 *  \param[in] type: tpye of item
 *  \return none
 */
#define v2a(vector, type)               ((type *)((vobject_t)(vector))->base)

/** 
 *  \brief define a const vector based on array，end use does not need to be deleted
 *  \param[in] array: array name
 *  \return const vector
 */
#define a2v(array)                      (&(VECTOR){1,array,sizeof(array[0]),sizeof(array)/sizeof(array[0]),sizeof(array)/sizeof(array[0])})

#endif
